Цель данного задания:
Сначала установим нужные нам версии библиотек. Мы гарантируем, что в данных версиях задание будет корректно отрабатывать.
После установки нужных версий, возможно, нужно перезагрузить среду (runtime), но скорее всего вам это не понадобится
На скачивание файла и установку понадобится не более 5 минут.
Важно! Устанавливать нужные версии нужно каждый раз, когда создается новый рантайм. Например, если вы 2 часа подряд делаете это задание, то подготовить библиотеки достаточно 1 раз. Но если вы, например, начали в понедельник, затем закрыли/выключили ноутбук, то при продолжении в среду, вам нужно будет запустить рантайм заново и следовательно заново установить библиотеки.
Важно! Если вы предпочитаете делать практические задания на своем личном ноутбуке, то проверьте, что вы установили рабочее окружение в соответствии с гайдом
! gdown 1pIw8GdGKY6fZ_XNPc6snimdV6lbXJ199
! pip install -r /content/requirements_small.txt
Downloading...
From: https://drive.google.com/uc?id=1pIw8GdGKY6fZ_XNPc6snimdV6lbXJ199
To: /content/requirements_small.txt
100% 374/374 [00:00<00:00, 1.29MB/s]
Collecting catboost==1.2.1 (from -r /content/requirements_small.txt (line 1))
Downloading catboost-1.2.1-cp310-cp310-manylinux2014_x86_64.whl (98.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 98.7/98.7 MB 7.3 MB/s eta 0:00:00
Requirement already satisfied: gdown==4.6.6 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 2)) (4.6.6)
Requirement already satisfied: h5py==3.9.0 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 3)) (3.9.0)
Requirement already satisfied: hyperopt==0.2.7 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 4)) (0.2.7)
Collecting ipympl==0.9.3 (from -r /content/requirements_small.txt (line 5))
Downloading ipympl-0.9.3-py2.py3-none-any.whl (511 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 511.6/511.6 kB 37.8 MB/s eta 0:00:00
Requirement already satisfied: ipywidgets==7.7.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 6)) (7.7.1)
Collecting lightgbm==4.0.0 (from -r /content/requirements_small.txt (line 7))
Downloading lightgbm-4.0.0-py3-none-manylinux_2_28_x86_64.whl (3.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.0/3.0 MB 65.6 MB/s eta 0:00:00
Requirement already satisfied: matplotlib==3.7.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 8)) (3.7.1)
Requirement already satisfied: matplotlib-inline==0.1.6 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 9)) (0.1.6)
Requirement already satisfied: numpy==1.23.5 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 10)) (1.23.5)
Requirement already satisfied: pandas==1.5.3 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 11)) (1.5.3)
Collecting pep8==1.7.1 (from -r /content/requirements_small.txt (line 12))
Downloading pep8-1.7.1-py2.py3-none-any.whl (41 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.5/41.5 kB 4.8 MB/s eta 0:00:00
Requirement already satisfied: plotly==5.15.0 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 13)) (5.15.0)
Collecting pycodestyle==2.11.0 (from -r /content/requirements_small.txt (line 14))
Downloading pycodestyle-2.11.0-py2.py3-none-any.whl (31 kB)
Collecting pytest==7.4.1 (from -r /content/requirements_small.txt (line 15))
Downloading pytest-7.4.1-py3-none-any.whl (324 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 324.2/324.2 kB 31.2 MB/s eta 0:00:00
Requirement already satisfied: scikit-image==0.19.3 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 16)) (0.19.3)
Requirement already satisfied: scikit-learn==1.2.2 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 17)) (1.2.2)
Collecting scipy==1.11.2 (from -r /content/requirements_small.txt (line 18))
Downloading scipy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (36.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 36.3/36.3 MB 37.4 MB/s eta 0:00:00
Requirement already satisfied: seaborn==0.12.2 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 19)) (0.12.2)
Requirement already satisfied: tqdm==4.66.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 20)) (4.66.1)
Collecting umap-learn==0.5.3 (from -r /content/requirements_small.txt (line 21))
Downloading umap-learn-0.5.3.tar.gz (88 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 88.2/88.2 kB 11.0 MB/s eta 0:00:00
Preparing metadata (setup.py) ... done
Collecting xgboost==1.7.6 (from -r /content/requirements_small.txt (line 22))
Downloading xgboost-1.7.6-py3-none-manylinux2014_x86_64.whl (200.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 200.3/200.3 MB 2.4 MB/s eta 0:00:00
Requirement already satisfied: graphviz in /usr/local/lib/python3.10/dist-packages (from catboost==1.2.1->-r /content/requirements_small.txt (line 1)) (0.20.1)
Requirement already satisfied: six in /usr/local/lib/python3.10/dist-packages (from catboost==1.2.1->-r /content/requirements_small.txt (line 1)) (1.16.0)
Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (3.13.1)
Requirement already satisfied: requests[socks] in /usr/local/lib/python3.10/dist-packages (from gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (2.31.0)
Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.10/dist-packages (from gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (4.11.2)
Requirement already satisfied: networkx>=2.2 in /usr/local/lib/python3.10/dist-packages (from hyperopt==0.2.7->-r /content/requirements_small.txt (line 4)) (3.2.1)
Requirement already satisfied: future in /usr/local/lib/python3.10/dist-packages (from hyperopt==0.2.7->-r /content/requirements_small.txt (line 4)) (0.18.3)
Requirement already satisfied: cloudpickle in /usr/local/lib/python3.10/dist-packages (from hyperopt==0.2.7->-r /content/requirements_small.txt (line 4)) (2.2.1)
Requirement already satisfied: py4j in /usr/local/lib/python3.10/dist-packages (from hyperopt==0.2.7->-r /content/requirements_small.txt (line 4)) (0.10.9.7)
Requirement already satisfied: ipython<9 in /usr/local/lib/python3.10/dist-packages (from ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (7.34.0)
Requirement already satisfied: ipython-genutils in /usr/local/lib/python3.10/dist-packages (from ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.2.0)
Requirement already satisfied: pillow in /usr/local/lib/python3.10/dist-packages (from ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (9.4.0)
Requirement already satisfied: traitlets<6 in /usr/local/lib/python3.10/dist-packages (from ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (5.7.1)
Requirement already satisfied: ipykernel>=4.5.1 in /usr/local/lib/python3.10/dist-packages (from ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (5.5.6)
Requirement already satisfied: widgetsnbextension~=3.6.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (3.6.6)
Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (3.0.9)
Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (1.2.0)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (4.45.1)
Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (1.4.5)
Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (23.2)
Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (3.1.1)
Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (2.8.2)
Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas==1.5.3->-r /content/requirements_small.txt (line 11)) (2023.3.post1)
Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly==5.15.0->-r /content/requirements_small.txt (line 13)) (8.2.3)
Requirement already satisfied: iniconfig in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.1->-r /content/requirements_small.txt (line 15)) (2.0.0)
Requirement already satisfied: pluggy<2.0,>=0.12 in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.1->-r /content/requirements_small.txt (line 15)) (1.3.0)
Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.1->-r /content/requirements_small.txt (line 15)) (1.2.0)
Requirement already satisfied: tomli>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.1->-r /content/requirements_small.txt (line 15)) (2.0.1)
Requirement already satisfied: imageio>=2.4.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image==0.19.3->-r /content/requirements_small.txt (line 16)) (2.31.6)
Requirement already satisfied: tifffile>=2019.7.26 in /usr/local/lib/python3.10/dist-packages (from scikit-image==0.19.3->-r /content/requirements_small.txt (line 16)) (2023.9.26)
Requirement already satisfied: PyWavelets>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image==0.19.3->-r /content/requirements_small.txt (line 16)) (1.5.0)
Requirement already satisfied: joblib>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-learn==1.2.2->-r /content/requirements_small.txt (line 17)) (1.3.2)
Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from scikit-learn==1.2.2->-r /content/requirements_small.txt (line 17)) (3.2.0)
Requirement already satisfied: numba>=0.49 in /usr/local/lib/python3.10/dist-packages (from umap-learn==0.5.3->-r /content/requirements_small.txt (line 21)) (0.58.1)
Collecting pynndescent>=0.5 (from umap-learn==0.5.3->-r /content/requirements_small.txt (line 21))
Downloading pynndescent-0.5.11-py3-none-any.whl (55 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 55.8/55.8 kB 3.5 MB/s eta 0:00:00
Requirement already satisfied: jupyter-client in /usr/local/lib/python3.10/dist-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.1.12)
Requirement already satisfied: tornado>=4.2 in /usr/local/lib/python3.10/dist-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.3.2)
Requirement already satisfied: setuptools>=18.5 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (67.7.2)
Collecting jedi>=0.16 (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5))
Downloading jedi-0.19.1-py2.py3-none-any.whl (1.6 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 24.3 MB/s eta 0:00:00
Requirement already satisfied: decorator in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (4.4.2)
Requirement already satisfied: pickleshare in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.7.5)
Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (3.0.41)
Requirement already satisfied: pygments in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (2.16.1)
Requirement already satisfied: backcall in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.2.0)
Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (4.9.0)
Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /usr/local/lib/python3.10/dist-packages (from numba>=0.49->umap-learn==0.5.3->-r /content/requirements_small.txt (line 21)) (0.41.1)
Requirement already satisfied: notebook>=4.4.1 in /usr/local/lib/python3.10/dist-packages (from widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.5.5)
Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.10/dist-packages (from beautifulsoup4->gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (2.5)
Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (3.6)
Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (2.0.7)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (2023.11.17)
Requirement already satisfied: PySocks!=1.5.7,>=1.5.6 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==4.6.6->-r /content/requirements_small.txt (line 2)) (1.7.1)
Requirement already satisfied: parso<0.9.0,>=0.8.3 in /usr/local/lib/python3.10/dist-packages (from jedi>=0.16->ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.8.3)
Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (3.1.2)
Requirement already satisfied: pyzmq<25,>=17 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (23.2.1)
Requirement already satisfied: argon2-cffi in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (23.1.0)
Requirement already satisfied: jupyter-core>=4.6.1 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (5.5.0)
Requirement already satisfied: nbformat in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (5.9.2)
Requirement already satisfied: nbconvert>=5 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.5.4)
Requirement already satisfied: nest-asyncio>=1.5 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.5.8)
Requirement already satisfied: Send2Trash>=1.8.0 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.8.2)
Requirement already satisfied: terminado>=0.8.3 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.18.0)
Requirement already satisfied: prometheus-client in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.19.0)
Requirement already satisfied: nbclassic>=0.4.7 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.0.0)
Requirement already satisfied: ptyprocess>=0.5 in /usr/local/lib/python3.10/dist-packages (from pexpect>4.3->ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.7.0)
Requirement already satisfied: wcwidth in /usr/local/lib/python3.10/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.2.12)
Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.10/dist-packages (from jupyter-core>=4.6.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (4.0.0)
Requirement already satisfied: jupyter-server>=1.8 in /usr/local/lib/python3.10/dist-packages (from nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.24.0)
Requirement already satisfied: notebook-shim>=0.2.3 in /usr/local/lib/python3.10/dist-packages (from nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.2.3)
Requirement already satisfied: lxml in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (4.9.3)
Requirement already satisfied: bleach in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.1.0)
Requirement already satisfied: defusedxml in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.7.1)
Requirement already satisfied: entrypoints>=0.2.2 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.4)
Requirement already satisfied: jupyterlab-pygments in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.3.0)
Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (2.1.3)
Requirement already satisfied: mistune<2,>=0.8.1 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.8.4)
Requirement already satisfied: nbclient>=0.5.0 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.9.0)
Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.5.0)
Requirement already satisfied: tinycss2 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.2.1)
Requirement already satisfied: fastjsonschema in /usr/local/lib/python3.10/dist-packages (from nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (2.19.0)
Requirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.10/dist-packages (from nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (4.19.2)
Requirement already satisfied: argon2-cffi-bindings in /usr/local/lib/python3.10/dist-packages (from argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (21.2.0)
Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (23.1.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (2023.11.1)
Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.31.1)
Requirement already satisfied: rpds-py>=0.7.1 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.13.2)
Requirement already satisfied: anyio<4,>=3.1.0 in /usr/local/lib/python3.10/dist-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (3.7.1)
Requirement already satisfied: websocket-client in /usr/local/lib/python3.10/dist-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.6.4)
Requirement already satisfied: cffi>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.16.0)
Requirement already satisfied: webencodings in /usr/local/lib/python3.10/dist-packages (from bleach->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.5.1)
Requirement already satisfied: sniffio>=1.1 in /usr/local/lib/python3.10/dist-packages (from anyio<4,>=3.1.0->jupyter-server>=1.8->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.3.0)
Requirement already satisfied: pycparser in /usr/local/lib/python3.10/dist-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (2.21)
Building wheels for collected packages: umap-learn
Building wheel for umap-learn (setup.py) ... done
Created wheel for umap-learn: filename=umap_learn-0.5.3-py3-none-any.whl size=82808 sha256=b11ce90b463edaa15c149845466c73db836355da2d4e62e2c55c0cdd2dc10959
Stored in directory: /root/.cache/pip/wheels/a0/e8/c6/a37ea663620bd5200ea1ba0907ab3c217042c1d035ef606acc
Successfully built umap-learn
Installing collected packages: pep8, scipy, pytest, pycodestyle, jedi, xgboost, lightgbm, pynndescent, catboost, umap-learn, ipympl
Attempting uninstall: scipy
Found existing installation: scipy 1.11.4
Uninstalling scipy-1.11.4:
Successfully uninstalled scipy-1.11.4
Attempting uninstall: pytest
Found existing installation: pytest 7.4.3
Uninstalling pytest-7.4.3:
Successfully uninstalled pytest-7.4.3
Attempting uninstall: xgboost
Found existing installation: xgboost 2.0.2
Uninstalling xgboost-2.0.2:
Successfully uninstalled xgboost-2.0.2
Attempting uninstall: lightgbm
Found existing installation: lightgbm 4.1.0
Uninstalling lightgbm-4.1.0:
Successfully uninstalled lightgbm-4.1.0
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
lida 0.0.10 requires fastapi, which is not installed.
lida 0.0.10 requires kaleido, which is not installed.
lida 0.0.10 requires python-multipart, which is not installed.
lida 0.0.10 requires uvicorn, which is not installed.
Successfully installed catboost-1.2.1 ipympl-0.9.3 jedi-0.19.1 lightgbm-4.0.0 pep8-1.7.1 pycodestyle-2.11.0 pynndescent-0.5.11 pytest-7.4.1 scipy-1.11.2 umap-learn-0.5.3 xgboost-1.7.6
import catboost
assert(catboost.__version__ == '1.2.1')
Теперь можно приступать к выполнению задания! :)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from copy import copy
Если Вы дальтоник, то можете воспользоваться готовой colormap из matplotlib (или найти свою):
plt.style.use('tableau-colorblind10')
from matplotlib.colors import ListedColormap
from sklearn.svm import LinearSVC, SVC
from sklearn.decomposition import PCA
from sklearn.model_selection import cross_val_score, cross_val_predict, cross_validate, train_test_split
from sklearn.metrics import make_scorer, accuracy_score, roc_auc_score
from sklearn.datasets import make_blobs, make_circles, make_moons
def make_moons_cls(size=1000, d=2):
X, y = make_moons(n_samples=size, noise=0.15)
if d > 2:
X = np.concatenate((X, np.random.normal(size=(size, d-2))), axis=1)
return X, y
def make_circles_cls():
X, y = make_circles()
def generate_data_with_imb_classes(size1=100, size2=10):
X = np.r_[(
np.random.normal(loc=1.0, size=(size1, 2)),
np.random.normal(loc=0.5, size=(size2, 2))
)]
y = np.ones(len(X))
y[-size2:] = 0
return X, y
def plot_separating_surface(X, y, cls, view_support=False, title=''):
x_min = min(X[:, 0]) - 0.1
x_max = max(X[:, 0]) + 0.1
y_min = min(X[:, 1]) - 0.1
y_max = max(X[:, 1]) + 0.1
h = 0.005
cm = plt.cm.RdBu
cm_bright = ListedColormap(['#FF0000', '#0000FF'])
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
Z = cls.predict(np.c_[xx.ravel(), yy.ravel()])
plt.figure(figsize=(10, 10))
if title:
plt.title(title)
plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', s=40, cmap=cm_bright)
if view_support:
plt.scatter(X[cls.support_, 0], X[cls.support_, 1],
c=y[cls.support_], edgecolors='k', s=150, cmap=cm_bright)
Z = Z.reshape(xx.shape)
plt.xticks(())
plt.yticks(())
plt.contourf(xx, yy, Z, cmap=cm, alpha=.3)
plt.show()
import gdown
gdown.download_folder('https://drive.google.com/drive/folders/1bp39_Jj0edo1lzxZ3DIoChsOVy5DVi1R?usp=sharing')
Retrieving folder list
Retrieving folder 1tv605hGxdQtd4zC787DbcRF0312gDeK_ imbalanced Processing file 14zd2xHDChSHtMWQ_TUzM8td7s8gzCO2u X_imb_test.npz.npy Processing file 1Qed066d3gUsUOZiUZu6aCrIH9f0yWKSc X_imb.npz.npy Processing file 1uD87Xbh4MMBBn5fsScrknI54SINIqory y_imb_test.npz.npy Processing file 1RR2VU_6WJMLo88k8C1VzBwb2Ibnz1yJf y_imb.npz.npy Retrieving folder 1uoI6vZWwIII1jd2k5TtsZTJ3JOkK0G6O public Processing file 1Win7ZtHLHEbDtX6x6O7vBJHwJviQxbp5 cX_test.npy Processing file 1MowPnLFAMEjjcAjDA4skE4OUFdmaiSY6 cX_train.npy Processing file 1VYA4N5wCQhwteQSZkDogFTha2xRv0FgW cy_train.npy Building directory structure completed
Retrieving folder list completed Building directory structure Downloading... From: https://drive.google.com/uc?id=14zd2xHDChSHtMWQ_TUzM8td7s8gzCO2u To: /content/05-SVM/imbalanced/X_imb_test.npz.npy 100%|██████████| 2.05k/2.05k [00:00<00:00, 1.14MB/s] Downloading... From: https://drive.google.com/uc?id=1Qed066d3gUsUOZiUZu6aCrIH9f0yWKSc To: /content/05-SVM/imbalanced/X_imb.npz.npy 100%|██████████| 2.05k/2.05k [00:00<00:00, 746kB/s] Downloading... From: https://drive.google.com/uc?id=1uD87Xbh4MMBBn5fsScrknI54SINIqory To: /content/05-SVM/imbalanced/y_imb_test.npz.npy 100%|██████████| 1.09k/1.09k [00:00<00:00, 3.20MB/s] Downloading... From: https://drive.google.com/uc?id=1RR2VU_6WJMLo88k8C1VzBwb2Ibnz1yJf To: /content/05-SVM/imbalanced/y_imb.npz.npy 100%|██████████| 1.09k/1.09k [00:00<00:00, 1.04MB/s] Downloading... From: https://drive.google.com/uc?id=1Win7ZtHLHEbDtX6x6O7vBJHwJviQxbp5 To: /content/05-SVM/public/cX_test.npy 100%|██████████| 8.13k/8.13k [00:00<00:00, 18.4MB/s] Downloading... From: https://drive.google.com/uc?id=1MowPnLFAMEjjcAjDA4skE4OUFdmaiSY6 To: /content/05-SVM/public/cX_train.npy 100%|██████████| 32.1k/32.1k [00:00<00:00, 43.7MB/s] Downloading... From: https://drive.google.com/uc?id=1VYA4N5wCQhwteQSZkDogFTha2xRv0FgW To: /content/05-SVM/public/cy_train.npy 100%|██████████| 6.53k/6.53k [00:00<00:00, 18.7MB/s] Download completed
['/content/05-SVM/imbalanced/X_imb_test.npz.npy', '/content/05-SVM/imbalanced/X_imb.npz.npy', '/content/05-SVM/imbalanced/y_imb_test.npz.npy', '/content/05-SVM/imbalanced/y_imb.npz.npy', '/content/05-SVM/public/cX_test.npy', '/content/05-SVM/public/cX_train.npy', '/content/05-SVM/public/cy_train.npy']
В ячейке ниже генерируется выборка, состоящая из объектов двух классов. Каждый объект представлен двумя координатами, так что объекты этой выборки можно отобразить на плоскости, используя функцию scatter из библиотеки matplotlib.
В этом задании вам надо будет обучить линейную разделяющую поверхность с помощью $\mbox{sklearn.svm.SVC(kernel='linear')}$, а также нелинейную c rbf-ядром с помощью $\mbox{sklearn.svm.SVC(kernel='rbf')}$. Остальные параметры методов можете оставить дефолтными. Делить выборку на обучение и валидацию сейчас не требуется, так как нас будет пока интересовать только форма разделяющей кривой.
X, y = make_moons_cls()
linear_svc = SVC(kernel='linear')
nonlinear_svc = SVC(kernel='rbf')
Визуализируем выборку
plt.figure(figsize=(8, 6))
plt.scatter(X[y == 0, 0], X[y == 0, 1], label='y=0')
plt.scatter(X[y == 1, 0], X[y == 1, 1], label='y=1')
plt.xlabel('$x_0$')
plt.ylabel('$x_1$')
plt.legend()
plt.grid()
Обучите модели и визуализируйте разделяющую поверхность для обеих моделей с помощью функции plot_separating_surface(). Посчитайте точность (accuracy) на обучающей выборке для каждой из моделей.
linear_svc.fit(X, y)
nonlinear_svc.fit(X, y)
plot_separating_surface(X, y, linear_svc, title='linear')
plot_separating_surface(X, y, nonlinear_svc, title='rbf')
print(f'Train Accuracy (linear): {accuracy_score(y, linear_svc.predict(X)):.3f}')
print(f'Train Accuracy (non linear): {accuracy_score(y, nonlinear_svc.predict(X)):.3f}')
Train Accuracy (linear): 0.869 Train Accuracy (non linear): 0.993
Сделайте вывод о получившихся результатах. Какая из моделей лучше подходит для данной выборки и почему?
Вывод: В нашем случае нужно нелинейное ядро, поэтому rbf показывает себя заметно лучше.
Продолжаем работать с выборкой и моделями из первой части. Для линейной и rbf-моделей рассмотрим опорные объекты, полученные после обучения. Визуализировать их можно, используя функуцию plot_separating_surface с параметром vissupport=True. Достанем опорные объекты из обученной модели с помощью поля model.support.
plot_separating_surface(X, y, nonlinear_svc, view_support=True)
Пункт 1 Обучим новые две модели $\mbox{SVC(kernel='rbf')}$, используя только опорные объекты построенные с помощью соответственно линейной (linear_svc) и нелинейной (nonlinear_svc) моделей из первой части.
# Учим модели только на опорных объектах
svc_on_linear_support = SVC(kernel='rbf').fit(X[linear_svc.support_, :], y[linear_svc.support_])
svc_on_rbf_support = SVC(kernel='rbf').fit(X[nonlinear_svc.support_, :], y[nonlinear_svc.support_])
plot_separating_surface(X, y, svc_on_linear_support)
plot_separating_surface(X, y, svc_on_rbf_support)
Задание: Сравните полученные разделяющие поверхности с нелинейной моделью (nonlinear_svc) из первой части. Какая из поверхностей больше похожа на нелинейнную модель из первой части и почему, опишите в выводе.
Вывод: Вторая поверхность больше похожа на nonlinear_svc, поскольку опорные вектора подбирались на ядра rbf. Использовать их в линейной модели, не имеет смысла. А на подобранных векторах rbf ядро показывает сильно похожий результат.
Пункт 2 Обучим модель $\mbox{SVC(kernel='rbf')}$, используя все объекты кроме тех, что являлись опорными для нелинейной модели из первой части (nonlinear_svc) и сравним эту модель вместе с svc_on_rbf_support с нелинейной моделью из первой части (nonlinear_svc). Визуализируйте разделяющие поверхности обеих моделей.
non_support_vectors = [i for i in range(len(X)) if i not in nonlinear_svc.support_]
svc_all_without_rbf_support = SVC(kernel='rbf').fit(X[non_support_vectors, :], y[non_support_vectors])
plot_separating_surface(X, y, svc_all_without_rbf_support)
plot_separating_surface(X, y, nonlinear_svc)
plot_separating_surface(X, y, svc_on_rbf_support)
Сделайте вывод: Сильно ли полученные поверхности отличаются от той, что была получена в первой части? Что произошло с пограничными объектами? Объясните полученные результаты.
Вывод: Полученные поверхности отличаются несильно, объясняется это тем, что после исключения опорных векторов, были выбраны похожие на них вектора и модель была заново обучена на них примерно также. Некоторые пограничные ответы изменились, например, в модели, которая исключила опорные вектора, потому что они не использовались в обучении.
Формы разделяющих поверхностей могут быть вариативными для нелинейного случая. Иногда, выбранная форма поверхности может плохо подходить для целевого распределения объектов. Особенно это может быть заметно, если соотношение классов в обучении отличается от тестового. Такое свойственно медицинским данным, где в обучающих данных часто наблюдается перекос в сторону больных, так как именно их данные чаще собираются.
Давайте обучим SVC на несбалансированных данных и построим разделяющую поверхность для тестовой выборки с другим соотношением классов.
X_distr1 = np.load('05-SVM/imbalanced/X_imb.npz.npy')
y_distr1 = np.load('05-SVM/imbalanced/y_imb.npz.npy')
X_distr2 = np.load('05-SVM/imbalanced/X_imb_test.npz.npy')
y_distr2 = np.load('05-SVM/imbalanced/y_imb_test.npz.npy')
# Модель с дефолтными параметрами, которую Вам предстоит улучшить
base_model = SVC()
base_model.fit(X_distr1, y_distr1)
plot_separating_surface(X_distr2, y_distr2, base_model)
Так как синих объектов было существенно больше в обучении, разделяющая поверхность отнесла к этому классу большую часть пространства около границы классов. При этом, из-за возросшего количества красных объектов в тестовой выборке, многие из них стали ошибочно относиться к другому классу.
Один из способов исправить эту проблему - это повлиять на форму поверхности с помощью задания весов классов, которые задаются через параметр class_weight в sklearn.svm.SVC. Особенно это может быть полезно в задачах, где известно, что распределение классов в обучающей выборке отличается от реального.
В данном задании вам будет дана выборка с несбалансированными данными. Кроме того, дана вторая выборка, в которой классы имеют то же распределение, но классы имеют другое соотношение. Вам нужно построить различные rbf-модели, меняя параметры весов классов и визуализировать разделяющие поверхности. Попробуйте улучшить качество на второй выборке (X_distr2, y_distr2), обучаясь только на первой (X_distr1, y_distr1) меняя параметры весов классов относительно дефолтных: class_weight={1: 1.0, 0: 1.0}. В качестве метрики, которую нужно оптимизировать нужно использовать accuracy на (X_distr2, y_dist2).
from itertools import product
w1_best, w2_best = 1.0, 1.0
best_acc = 0
grid = [0.01, 0.1, 0.5, 1.0, 5, 10, 100, 1000]
for w1, w2 in product(grid, grid):
svc_cls = SVC(C=1.0, class_weight={1: w1, 0: w2})
svc_cls.fit(X_distr1, y_distr1)
acc = accuracy_score(y_distr2, svc_cls.predict(X_distr2))
if acc > best_acc:
best_acc = acc
w1_best = w1
w2_best = w2
print(f'Weight1: {w1_best},\nWeight2: {w2_best},\nBest accuracy: {best_acc}')
Weight1: 0.1, Weight2: 5, Best accuracy: 0.9666666666666667
best_svc_cls = SVC(C=1.0, class_weight={1: w1_best, 0: w2_best})
best_svc_cls.fit(X_distr1, y_distr1)
plot_separating_surface(X_distr2, y_distr2, best_svc_cls)
print('My best classifier:')
print('Accuracy:', accuracy_score(y_distr2, best_svc_cls.predict(X_distr2)))
My best classifier: Accuracy: 0.9666666666666667
Возможность строить нелинейные поверхности может сильно улучшить качество, но и несет риск переобучения. В этом задании предстоит обучить лучшую svm модель и получить хорошее качество на тесте в системе тестирования. Для контроля переобучения рекомендуется пользоваться кросс-валидацией. Для улучшения качества рекомендуется подбирать
Также не забывайте, что при решении задач машинного обучения полезно смотреть в данные :)
Все csv-таблицы с данными вы можете взять из публичного теста, который также есть в проверяющей системе. Для этого распакуйте архив с публичными тестами и положите файлы в рабочей директории (рядом с ноутбуком)
X_train = np.load('05-SVM/public/cX_train.npy')
y_train = np.load('05-SVM/public/cy_train.npy')
X_test = np.load('05-SVM/public/cX_test.npy')
X_train.shape, y_train.shape, X_test.shape
((800, 5), (800,), (200, 5))
X = X_train
y = y_train.ravel()
plt.scatter(X[y == 0, 4], X[y == 0, 3], label='y=0')
plt.scatter(X[y == 1, 4], X[y == 1, 3], label='y=1')
plt.legend()
<matplotlib.legend.Legend at 0x78e51825d3c0>
Отправьте код обучения модели с оптимальными параметрами в проверяющую систему, воспользовавшись приложенным шаблоном svm_solution.py. Кросс-валидацию параметров в посылаемом решении делать не нужно -- достаточно подобрать, например, их тут, а в решении уже обучать модель с оптимальными параметрами.
В предыдущей части Вы обучили хорошую SVM модель, подбирая гиперпараметры модели. Давайте теперь попробуем обучить логистическую регрессию на этой же выборке, и по кросс-валидации оценить влияние гиперпараметров на линейную модель.
import warnings
warnings.filterwarnings('ignore')
from sklearn.linear_model import LogisticRegression
import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn import metrics
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
def train_logreg_and_predict(train_features, train_target, test_features):
scaler = StandardScaler()
train_features = scaler.fit_transform(train_features)
parameters = {
'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'],
'penalty':['none', 'elasticnet', 'l1', 'l2'],
'C':[0.001, 0.01, 0.1, 1, 10, 100]
}
LR = LogisticRegression(random_state=42)
clf = GridSearchCV(LR, parameters, cv=5, scoring="accuracy", verbose=1)
clf.fit(train_features, train_target)
print(clf.best_params_["solver"], clf.best_params_["penalty"], clf.best_params_["C"])
print(f"Best score - {clf.best_score_}")
train_logreg_and_predict(X_train[:, 3:5], y_train, X_test)
Fitting 5 folds for each of 120 candidates, totalling 600 fits saga l1 1 Best score - 0.82125
Сделайте выводы о влиянии выбора гиперпараметров на качество обучения линейной и SVC моделей. Также опишите, какие преобразования выборки/подбор каких гиперпараметров помогли добиться высокого качества на кросс-валидации в данной задаче.
Вывод: Подбор гиперпараметров повышает качество модели. Для логистической регрессии комбинация saga и l1-регуляризации дали наилучший результат, а в SVC наилучший результат показала комбинация rbf и C = 0.5. На качетсво повлияло то, что были отброшены первые два признака выборки, как незначимые.
В предыдущих заданиях мы убедились в мощности и гибкости моделей SVM. Теперь ответим на вопрос, насколько реально обучить модель SVM на выборках большого размера или с большим числом признаков.
Нужно провести два эксперимента. В первом перебирать размер выборки и для каждого запуска посчитать реальное время обучения модели. При этом делить выборку на обучение и тестирование не нужно. Также качество обученной модели в данном эксперименте не имеет значение. Размеры выборки предлагается перебирать в диапазоне range(1000, 10001, 1000) с использованием generate_data_with_balanced_classes(size=n).
Необходимо сравнить время обучения SVM с логистической регрессией. Для этого замеры повторите также для модели sklearn.linear_model.LogisticRegression. Время обучения одной модели замеряйте с помощью стандартной библиотеки time (пример в ячейке ниже).
Вы можете поставить эксперименты и с большими выборками, чем предлагается в задании (сгенерировать их),
тогда эффект должен быть виден еще сильнее.
Внимание! во время замеров времени работы, отключите сторонние процессы, занимающие CPU, иначе замеры времени работы окажутся некорректными. Помните, что времени работы в зависимости от числа данных и признаков должно меняться монотонно, без ступенчатых изменений (за исключением небольшого шума).
# Как замерять время
import time
time_start = time.time()
time.sleep(1) # Вместо этой команды - запуск замеряемого алгоритма
print("Время работы:", time.time() - time_start)
Время работы: 1.000631332397461
def generate_data_with_balanced_classes(size=500, d=2, noise_scale=0.1):
X = np.random.normal(size=(size*2, d))
mask = X[:, 1] ** 2 > X[:, 0] - 0.1 + np.random.normal(scale=noise_scale)
y = np.ones(len(X))
y[mask] = 0
return X, y
from tqdm import tqdm
time_svc = {
10: [],
1001: [],
100: []
}
time_logreg = {
10: [],
1001: [],
100: []
}
logreg = LogisticRegression(random_state=42)
svc = SVC(random_state=42)
for n in tqdm(range(1000, 10001, 1000)):
for d in [10, 1001, 100]:
X, y = generate_data_with_balanced_classes(size=n, d=d)
time_start = time.time()
svc.fit(X, y)
t = time.time() - time_start
time_svc[d].append(t)
time_start = time.time()
logreg.fit(X, y)
t = time.time() - time_start
time_logreg[d].append(t)
100%|██████████| 10/10 [28:15<00:00, 169.51s/it]
Во втором эксперименте предлагается проделать то же самое, что и в первом эксперименте, только меняя размерность пространства признаков. Для этого можете воспользоваться функцией generate_data_with_balanced_classes(dim=d). Признаки предлагается перебирать по сетке $range(10, 1001, 100)$.
n = range(100, 10001, 1000)
plt.figure(figsize=(15, 4))
plt.subplot(1, 3, 1)
plt.plot(n, time_svc[10], label = "SVC")
plt.plot(n, time_logreg[10], label = "LogReg")
plt.yscale('log')
plt.legend()
plt.xlabel('Размер выборки', fontsize=16)
plt.ylabel('Время', fontsize=16)
plt.title('d=10')
plt.subplot(1, 3, 2)
plt.plot(n, time_svc[1001], label = "SVC")
plt.plot(n, time_logreg[1001], label = "LogReg")
plt.yscale('log')
plt.legend()
plt.xlabel('Размер выборки', fontsize=16)
plt.ylabel('Время', fontsize=16)
plt.title('d=1001')
plt.subplot(1, 3, 3)
plt.plot(n, time_svc[100], label = "SVC")
plt.plot(n, time_logreg[100], label = "LogReg")
plt.yscale('log')
plt.legend()
plt.xlabel('Размер выборки', fontsize=16)
plt.ylabel('Время', fontsize=16)
plt.title('d=100')
plt.tight_layout()
Постройте графики времени работы в зависимости от числа объектов для SVM и логистической регрессии, сравните их и сделайте выводы.
Придумывая обоснование получившимся результатам попробуйте использовать вид решаемой задачи в SVM, который был дан вам на лекции.
Вывод: Сложность обучения логистической регрессии O(nd)
Сложность обучения нелинейной SVM в среднем между O(n^2) и O(n^3)
График SVC растет намного быстрее чем у логстической регресии.
Если уменьшение числа объектов сложная и зачастую невозможная задача, то для понижения числа признаков существует стандартное решение. В предыдущих заданиях Вы уже сталкивались с l1-регуляризацией, которая позволяла уменьшить число признаков в задаче линейной классификации/регрессии. Однако для большинства ML-алгоритмов такой способ уменьшения числа признаков неприменим.
Зато существует стандартное для всех алгоритмов понижение размерности входа. Данный алгоритм называется Principal Component Analysis (PCA, метод главных компонент). Он находит такое линейное пространство меньшей размерности $k$ ($k << d$, где d изначальная размерность входа), проекция на которое теряет меньше всего информации. Подробнее об этом можете почитать тут https://scikit-learn.org/stable/modules/decomposition.html#pca.
Эксперимент: Проекция в очень малое число координат сильно "упрощает" выборку, из-за чего качество решения задачи может в итоге упасть. В следующем эксперименте предлагается исследовать зависимость скорости работы метода и качества решения задачи при использовании понижения размерности. Требуется построить два графика:
При этом под полным циклом обучения подразумевается обучение PCA + обучение SVM. Данные для обучения: первые две координаты - луны, которые были в первом задании, а остальные координаты, случайные. Таким образом, без понижения размерности SVM с rbf ядром должен иметь точность близкую к 100\%. Чтобы лучше видеть эффект на графиках, можете менять размер генерируемой выборки. Для данных размеров $k$ рекомендуется перебирать от 10 до 500 (тогда будет видна требуемая закономерность).
P.S. Не забывайте делить выборку на обучение и валидацию в этом эксперименте (так как мы смотрим на качество, мы хотим считать его честно). При этом PCA как и любой другой алгоритм ML тоже нельзя учить на тесте. Общая схема применения PCA описана в ячейках ниже.
X_moons, y_moons = make_moons_cls(2000, 1000)
X_moons.shape
(2000, 1000)
plt.scatter(X_moons[:, 0], X_moons[:, 1], c=y_moons)
plt.xlabel('$x_0$')
plt.ylabel('$x_1$')
plt.show()
plt.scatter(X_moons[:, 0], X_moons[:, 2], c=y_moons)
plt.xlabel('$x_0$')
plt.ylabel('$x_2$')
plt.show()
plt.scatter(X_moons[:, 2], X_moons[:, 3], c=y_moons)
plt.xlabel('$x_2$')
plt.ylabel('$x_3$')
plt.show()
Казалось бы понизить размерность в этой задаче достаточно легко, нужно просто выбрать только первые две координаты. Однако из-за нелинейности разделяющей поверхности, для PCA это задача нетривиальна. Такая же ситуация наблюдается и в большинстве прикладных задач. Теперь переходите к эксперименту :)
# Пример правильного обучения PCA с делением на train/test
pca_model = PCA(n_components=500)
X_moons_train, X_moons_test, y_moons_train, y_moons_test = train_test_split(
X_moons, y_moons, test_size=0.2) # делим выборку на трейн тест для оценки качества всего алгоритма
X_train_for_pca, X_train_for_svc, y_train_for_pca, y_train_for_svc = train_test_split(
X_moons_train, y_moons_train, test_size=0.5) # делим выборку на трейн тест для оценки качества всего алгоритма
print(X_moons.shape, y_moons.shape)
print(X_moons_train.shape, y_moons_train.shape)
print(X_train_for_pca.shape, y_train_for_pca.shape)
# Учим PCA
pca_model.fit(X_train_for_pca)
# Применяем PCA
X_moons_test_transformed = pca_model.transform(X_moons_test)
X_train_for_svc_transformed = pca_model.transform(X_train_for_svc)
print(X_train_for_svc_transformed.shape)
# Учим SVC (на другой выборке чтобы не переобучиться)
svc_on_transformed = SVC(kernel='rbf')
svc_on_transformed.fit(X_train_for_svc_transformed, y_train_for_svc)
preds = svc_on_transformed.predict(X_moons_test_transformed)
print('Accuracy after PCA:', accuracy_score(preds, y_moons_test))
(2000, 1000) (2000,) (1600, 1000) (1600,) (800, 1000) (800,) (800, 500) Accuracy after PCA: 0.535
time_n = []
accuracy_n = []
n_components = range(10, 501, 20)
for n in n_components:
pca_model = PCA(n_components=n)
X_moons_train, X_moons_test, y_moons_train, y_moons_test = train_test_split(
X_moons, y_moons, test_size=0.2)
X_train_for_pca, X_train_for_svc, y_train_for_pca, y_train_for_svc = train_test_split(
X_moons_train, y_moons_train, test_size=0.5)
time_start = time.time()
pca_model.fit(X_train_for_pca)
X_moons_test_transformed = pca_model.transform(X_moons_test)
X_train_for_svc_transformed = pca_model.transform(X_train_for_svc)
svc_on_transformed = SVC(kernel='rbf')
svc_on_transformed.fit(X_train_for_svc_transformed, y_train_for_svc)
t = time.time() - time_start
preds = svc_on_transformed.predict(X_moons_test_transformed)
a = accuracy_score(preds, y_moons_test)
time_n.append(t)
accuracy_n.append(a)
plt.figure(figsize=(16, 8))
plt.subplot(1, 2, 1)
plt.plot(n_components, time_n)
plt.xlabel('n_components', fontsize=16)
plt.ylabel('Время', fontsize=16)
plt.title('Time')
plt.subplot(1, 2, 2)
plt.plot(n_components, accuracy_n)
plt.xlabel('n_components', fontsize=16)
plt.ylabel('Точность', fontsize=16)
plt.title('Accuracy')
Text(0.5, 1.0, 'Accuracy')
Опишите в выводе как ведет себя качество решения задачи и время работы в зависимости от числа компонент в PCA.
Вывод: Чем больше колличество компонент в PCA, тем дольше время цикла. Чем больше компонент, тем в среднем выше точность.
Иногда в задаче классификации важно знать уверенность отнесения к тому или иному классу. В SVM за это отвечает параметр отступа (margin), который можно посчитать, используя model.decision_function(X). Именно отступ до разделяющей кривой пытается максимизироавть модель во время обучения. Однако по нему сложно утверждать с какой вероятностью объект относится к тому или иному классу.
Чтобы это понять давайте построим следующую кривую: 1) нормализуем отступы так, чтобы они лежали в диапазоне от 0 до 1;
2) разделим все объекты на бины по нормализованному оступу (например на [0, 0.1), [0.1, 0.2)...);
3) для каждого бина построим точку с координатой x - равной среднему значению нормализованного оступа внутри бина, и с координатой y - равной доле объектов класса 1 внутри бина.
Заметим теперь, что если бы нормализованный отступ приблизительно равнялся вероятности отнесения к классу, то бину [x, x + 0.1) должна была бы соответствовать точка с координатой Х принадлежащей [x, x + 0.1) и координатой Y в том же диапазоне. Таким образом, чем лучше скоры модели показывают вероятность отнесения к классу 1, тем больше калибровочная кривая похожа на прямую из точки (0, 0) в (1, 1).
Кроме того построим аналогично кривую для логистической регрессии, взяв вместо нормализованного отступа - вероятность отнесения к первому классу через predict_proba. Так как логистическая регрессия оптимизирует LogLoss и её выходом уже являются вероятности отнесения к классам, будем ожидать что её кривая хорошо ляжет на прямую из (0, 0) в (1, 1).
from sklearn.datasets import make_classification
from sklearn.calibration import calibration_curve
from sklearn.linear_model import LogisticRegression
# generate 2 class dataset
X, y = make_classification(n_samples=5000, n_classes=2, weights=[1,1], random_state=1)
# split into train/test sets
trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.5, random_state=2)
# fit a model
model = SVC()
model.fit(trainX, trainy)
# predict probabilities
probs = model.decision_function(testX)
# reliability diagram
fop, mpv = calibration_curve(testy, probs, n_bins=10, normalize=True)
# plot perfectly calibrated
# plot model reliability
plt.plot(mpv, fop, marker='.', label='SVC')
plt.xlabel('classifier score')
plt.ylabel('[label=1] ratio')
logistic_model = LogisticRegression()
logistic_model.fit(trainX, trainy)
logistic_probs = logistic_model.predict_proba(testX)[:, 1]
# reliability diagram
log_fop, log_mpv = calibration_curve(testy, logistic_probs, n_bins=10, normalize=True)
# plot perfectly calibrated
# plot model reliability
plt.plot(log_mpv, log_fop, marker='.', label='logistic')
plt.plot([0, 1], [0, 1], linestyle='--', label='ideal')
plt.legend()
plt.show()
Вот мы и увидели проблему, линия отступов не ложится на пунктирную линию, что означает что оступы не соотвествуют реальным вероятностям отнесения к тому или иному классу.
Но не всё пропало! Из отступов всё ещё можно получить вероятность отнесения к классу. Для этого существует такая процедура как калибровка вероятностей, при которой отступ для каждого объекта преобразовывается таким образом, чтобы соответствовать вероятности класса. После такого преобразования, полученное число становится интерпретируемой мерой уверенности модели.
В данном задании Вам прелагается обучить логистическую регрессию на отступах модели, которая по оступу (margin) предсказывала бы класс. Именно вероятности этой калибровочной модели и будут нашими верными оценками вероятности класса для объекта:
$p(y_i | x_i) = p(y_i | margin_i)$
Для этого Вам потребуется написать несложный класс CalibratingLogisticRegression. И проверить что новые предсказания дают правильную калибровочную кривую
class CalibratingLogisticRegression:
def __init__(self):
self.model = LogisticRegression()
def fit(self, x, y):
assert len(x.shape) == 1 or x.shape[1] == 1
self.model.fit(x, y)
def predict_proba(self, x):
assert len(x.shape) == 1 or x.shape[1] == 1
return self.model.predict_proba(x)[:, 1]
Калибровочную модель и исходную модель нельзя учить на одних и тех же данных, чтобы избежать переобучения. (распределение отступов на обучении и тестовой выборке, скорее всего очень сильно отличается)
model = SVC()
N = len(trainX) // 2
model.fit(trainX[:N], trainy[:N])
SVC()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
SVC()
margin = model.decision_function(trainX[N:]).reshape(-1,1)
# Учим калибровочную модель на второй половине данных
calibrating_model = CalibratingLogisticRegression()
calibrating_model.fit(margin, trainy[N:])
prob = calibrating_model.predict_proba(margin)
# Как это выглядит на обучении
margin_sorted, probs_sorted_by_margin = zip(*sorted(zip(margin, prob)))
plt.figure(figsize=(10, 10))
plt.plot(margin, trainy[N:], 'ro')
plt.plot(margin_sorted, probs_sorted_by_margin, 'b')
plt.show()
probs = calibrating_model.predict_proba(model.decision_function(testX).reshape(-1,1))
# reliability diagram
fop, mpv = calibration_curve(testy, probs, n_bins=10, normalize=True)
# plot perfectly calibrated
plt.plot([0, 1], [0, 1], linestyle='--')
# plot calibrated reliability
plt.plot(mpv, fop, marker='.')
plt.show()
Обратите внимание, что кривая для откалиброванных отступов должня также строиться для бинов и состоянть из n_bins точек. Если у Вас получилось кривая из трёх точек, Вы что-то сделали неправильно :)
Сделайте выводы о полученной модели. В каких задачах калибровка вероятностей могла бы быть полезной?
Выводы: Модель хорошо показывает вероятности для вероятности a точек. Полученная кривая близка к заданной прямой. Калибровка может быть полезна для задач классификации (калибровка вероятностей может быть полезной, когда важна точность оценок вероятностей для каждого класса); задач ранжирования (позволит улучшить качество предсказаний).
Найдите мем про SVM лучше чем этот:
Важно: самый простой способ вставить картинку будет через Google Colab (даже если вы изначально делали не в нем). Нажмите на "+ Text", в появившейся ячейке сделайте прикрепление картинки (как на скринах). Тогда ваша картинка "зашифруется" и будет корректно отображаться при конвертации в html